#pragma once
#include <Display/camera_interface.h>
using glm::vec3;

namespace PhysLeo{

/**
 * Camera properties:
 * 1. cameraPosition: where the camera is located
 * 2. focus_position_: where the camera is looking at
 * 3. cameraUp: up direction of the camera
 * 4. fov: field of view of the camera within [0,180]
 * 5. nearClip: distance from the camera position to the near clip plane
 * 6. farClip: distance from the camera position to the far clip plane
 * 7. viewAspect: aspect of the camera's view (width/height)
 */
class Camera:public CameraInterface
{
public:

    /*
     * default camera: positioned at origin, up direction y axis, look into negative z axis (0,0,-1)
     * field of view 45 degrees, view aspect 640/480, near clip 1.0, far clip 100.0
     */
    Camera();
 
    Camera(const vec3 &camera_position, const vec3 &camera_up, const vec3 &focus_position,
           float field_of_view, float view_aspect, float near_clip, float far_clip);

    //rotate the camera around the focus (spherical camera)
    void orbitUp(float rad);
    void orbitDown(float rad);
    void orbitRight(float rad);
    void orbitLeft(float rad);

    //zoom in and zoom out
    void zoomIn(float dist);
    void zoomOut(float dist);

    //change the up direction or look direction (focus position) via yaw, pitch, and roll
    //http://sidvind.com/wiki/Yaw,_pitch,_roll_camera
    void yaw(float rad);
    void pitch(float rad);
    void roll(float rad);

    //translate the camera along with the focus
    void translateUp(float dist);
    void translateDown(float dist);
    void translateRight(float dist);
    void translateLeft(float dist);

    //getters && setters
	vec3 getPosition() override { return camera_position_; }
	vec3 getUpDirection() override { return camera_up_; }
	vec3 getFocusPosition() override { return focus_position_; }
	float getFov() override { return fov_; }
	float getAspect() override { return view_aspect_; }
	float getNearClip() override { return near_clip_; }
	float getFarClip() override { return far_clip_; }

	void setPosition(const vec3 position) { camera_position_ = position; }
	void setUpDirection(const vec3 up) { camera_up_ = up; }
	void setFocusPosition(const vec3 focus) { focus_position_ = focus; }
	void setFov(const float fov) { fov_ = fov; }
	void setAspect(const float aspect) { view_aspect_ = aspect; }
	void setNearClip(const float near_clip) { near_clip_ = near_clip; }
	void setFarClip(const float far_clip) { far_clip_ = far_clip; }

protected:
    vec3 camera_position_;
    vec3 camera_up_;
    vec3 focus_position_;
    float fov_;
    float view_aspect_;
    float near_clip_;
    float far_clip_;
};

}  //end of namespace Physika

